﻿using ImModels.View;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Primitives;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text;
using CommonlyUtils;
using ImClientApi.Utils;
using ImModels.Service.Models.Data;

namespace ImClientApi.Middle
{
    /// <summary>
    /// 权限中间件
    /// </summary>
    public static class AuthorizeMiddler
    {
        /// <summary>
        /// 自定义权限验证
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseImCustomerAuthorize(this IApplicationBuilder app)
        {
            return app.UseMiddleware<ImCustomerAuthMiddlewareExtensions>();
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public class ImCustomerAuthMiddlewareExtensions
    {
        private readonly RequestDelegate _next;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="next"></param>
        public ImCustomerAuthMiddlewareExtensions(RequestDelegate next)
        {
            _next = next;
        }

        /// <summary>
        /// 记录请求日志
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            try
            {
                string srcip = context?.Connection?.RemoteIpAddress?.ToString() ?? "";
                var sb = new StringBuilder();

                #region 访问日志记录
                string path = context?.Request.Path.Value ?? "";
                if (string.IsNullOrEmpty(path) || path.Contains(".js") || path.Contains(".css") || path.Contains(".html") || path.Contains(".png") || path.Contains(".jpg") || path.Contains(".bmp"))
                {
                    return;
                }
                else
                {
                    context.Request.EnableBuffering();
                    sb.AppendLine($"{srcip} {context.Request.Method} {context.Request.Host}{context.Request.Path}{context.Request.QueryString}");
                    sb.AppendLine($"Header:{JsonSerializer.Serialize(context.Request.Headers.ToList())}");

                    //if (!path.ToLower().Contains("api/wxllpay/upfile"))
                    //{
                    //    //启用读取request
                    //    var requestReader = new StreamReader(context.Request.Body);
                    //    var requestContent = requestReader.ReadToEnd();
                    //    sb.AppendLine($"RequestBody:{requestContent}");
                    //    context.Request.Body.Position = 0;
                    //}
                }
                #endregion

                #region 权限验证
                var jwtAuth = context?.GetEndpoint()?.Metadata?.GetMetadata<JwtAuthAttribute>() ?? null;
                var anyUser = context?.GetEndpoint()?.Metadata?.GetMetadata<AnyUserAttribute>() ?? null;

                if (anyUser == null && jwtAuth != null)
                {
                    //用户权限
                    context.Request.Headers.TryGetValue("Authorization", out StringValues authStr);

                    var checktoken = JwtHepler.IsSuccessReInfo(authStr);

                    if (string.IsNullOrWhiteSpace(authStr) || !checktoken.StartsWith("success"))
                    {
                        await ResponseError(context, (string.IsNullOrWhiteSpace(checktoken) ? "Unanthorized" : checktoken), 302);

                        sb.AppendLine("JwtAuth Fail 302 " + (string.IsNullOrWhiteSpace(checktoken) ? "Unanthorized" : checktoken));

                        LogHelper.CallLog(sb.ToString(), "ApiLog");
                        return;
                    }
                }
                #endregion
                sb.AppendLine("WhiteList.Pass JwtAuth.Pass");
                LogHelper.CallLog(sb.ToString(), "ApiLog");

                await _next(context);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex, "ApiLogAuth异常");
                await ResponseError(context, ex.Message);
            }
            await Task.CompletedTask;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="errormsg"></param>
        /// <param name="retcode">200表示正常 500 程序错误，530不可用，401未授权 404 未找到 302登录信息过期 其他数字请联系提供方查询对应描述</param>
        private async Task ResponseError(HttpContext context, string errormsg, int retcode = 503)
        {
            //判断是否已经把Header发送出去，如果已经发送了，则不能再进行header的设置了
            if (!context.Response.HasStarted)
            {
                //无授权信息 二次判断 是否404
                //var retcode = 401;//默认404
                var novalue_response = new ResView()
                {
                    code = retcode,
                    msg = retcode + " " + errormsg,
                };

                //hack 返回数据的格式 首字母小写
                JsonSerializerOptions options = new JsonSerializerOptions()
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
                    PropertyNameCaseInsensitive = true,
                    WriteIndented = false
                };
                //enchack
                var jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(novalue_response, options);
                context.Response.ContentType = "application/json";
                context.Response.StatusCode = retcode;
                await context.Response.BodyWriter.WriteAsync(jsonUtf8Bytes);
                await context.Response.BodyWriter.FlushAsync();
                await context.Response.CompleteAsync();
            }
        }
    }
}
